﻿package com.winglish.as3.loader
{
	import flash.display.Loader;
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.SecurityErrorEvent;
	import flash.net.URLRequest;
	import flash.system.LoaderContext;
	
	public class SWFLoader extends EventDispatcher
	{
		private var _url: String;
		private var _loader: Loader;
		private var _request: URLRequest;
		private var _context : LoaderContext;
		private var _isReady: Boolean;
		private var _isLoading: Boolean;
		private var _bytesTotal: uint;
		private var _bytesLoaded: uint;
		
		/**
		 * swf 로더
		 * @param	url
		 */
		public function SWFLoader( url: String )
		{
			_url = url;
			if( _url ) load( _url );
		}
		/**
		 * swf 로드
		 * @param	url
		 */
		private function load( url: String ): void
		{			
			_isLoading = true;
			_request = new URLRequest( url );
			_loader = new Loader();
			_context = new LoaderContext();
			_context.checkPolicyFile = true;
			
			addEvent();
			_loader.load( _request, _context );
		}
		
		/**
		 * 이벤트 등록.
		 */
		private function addEvent(): void
		{
			//_loader.contentLoaderInfo.addEventListener( Event.OPEN, hnOpen );
			//_loader.contentLoaderInfo.addEventListener( Event.CLOSE, hnClose );
			_loader.contentLoaderInfo.addEventListener( ProgressEvent.PROGRESS, hnProgress );
			_loader.contentLoaderInfo.addEventListener( IOErrorEvent.IO_ERROR, hnError );
			//_loader.contentLoaderInfo.addEventListener( SecurityErrorEvent.SECURITY_ERROR, hnSecurity );
			_loader.contentLoaderInfo.addEventListener( Event.INIT, hnInit );
			
		}
		
		/**
		 * 이벤드 삭제.
		 */
		private function removeEvent(): void
		{
			//_loader.contentLoaderInfo.removeEventListener( Event.OPEN, hnOpen );
			//_loader.contentLoaderInfo.removeEventListener( Event.CLOSE, hnClose );
			_loader.contentLoaderInfo.removeEventListener( ProgressEvent.PROGRESS, hnProgress );
			_loader.contentLoaderInfo.removeEventListener( IOErrorEvent.IO_ERROR, hnError );
			//_loader.contentLoaderInfo.removeEventListener( SecurityErrorEvent.SECURITY_ERROR, hnSecurity );
			_loader.contentLoaderInfo.removeEventListener( Event.INIT, hnInit );
		}
		
		/**
		 * swf play end를 위한 이벤트 등록.
		 */
		public function startEnterFrame():void {
			if (_loader.content) _loader.content.addEventListener(Event.ENTER_FRAME, enterFrame);
		}
		/**
		 * swf open 이벤트.
		 * @param	e
		 */
		private function hnOpen( e: Event ): void
		{
			if( e != null ) dispatchEvent( new Event( Event.OPEN ) );
		}
		
		/**
		 * swf close 이벤트.
		 * @param	e
		 */
		private function hnClose( e: Event ): void
		{
			if( e != null ) dispatchEvent( new Event( Event.CLOSE ) );
		}
		
		/**
		 * swf progress 이벤트.
		 * @param	e
		 */
		private function hnProgress( e: ProgressEvent ): void
		{
			_bytesTotal = e.bytesTotal;
			_bytesLoaded = e.bytesLoaded;
			dispatchEvent( new ProgressEvent( ProgressEvent.PROGRESS, false, false, _bytesLoaded, _bytesTotal ) );
		}
		
		/**
		 * swf error 이벤트.
		 * @param	e
		 */
		private function hnError( e: IOErrorEvent ): void
		{
			trace( e );
		}
		
		/**
		 * swf securityError 이벤트.
		 * @param	e
		 */
		private function hnSecurity( e: SecurityErrorEvent ): void
		{
			trace( e );
		}
		
		/**
		 * swf init 이벤트.
		 * @param	e
		 */
		private function hnInit( e: Event ): void
		{
			_isReady = true;
			removeEvent();
			dispatchEvent( new Event( Event.INIT ) );
		}
			
		/**
		 * swf complete 이벤트.
		 * @param	e
		 */
		private function enterFrame(e:Event):void {
			if (e.target.currentFrame == e.target.totalFrames) {
				dispatchEvent( new Event( "swfPlayEnd" ) );
				e.target.removeEventListener(Event.ENTER_FRAME, enterFrame);
			}
			
		}
		
		/**
		 * swf 닫기.
		 */
		public function close(): void
		{
			if( _isLoading && !_isReady ){
				_isLoading = false;
				removeEvent();
				_loader.close();
				_loader = new Loader();
			}
		}
		
		/**
		 * 객체 닫기.
		 */
		public function destroy(): void
		{
			close();
			removeEvent();
			_loader = null;
			_context = null;
			_request = null;
		}
		
		/**
		 * swf 로드 퍼센트.
		 * @return
		 */
		public function getPercent(): Number
		{
			var per: Number = _bytesLoaded / _bytesTotal;
			if( isNaN( per ) || !isFinite( per ) ) per = 0;
			return per
		}
		
		/**
		 * 로드한 swf.
		 * @return
		 */
		public function getContent(): MovieClip
		{
			return _loader.content as MovieClip;
		}
		
		/**
		 * 로드한 swf Url.
		 */
		public function get getUrl():String {
			return _url;
		}
	}
}